﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Biosek
{

	public class DestinoHelper
	{
		public static IList<IList<T>> LoadPlain<T>(string filename) where T : struct
		{
			int phase = 0;
			int samples = 0;
			int alpha = 0;
			List<T[]> lista = null;
			using (var reader = new StreamReader(filename))
			{
				while (!reader.EndOfStream)
				{
					var line = reader.ReadLine().Trim();
					if (line.Length == 0 || line[0] == '#')
					{
						continue;
					}
					var parts = line.Split(' ');
					if (phase == 0)
					{
						// Reconoce la cabecera
						samples = int.Parse(parts[0]);
						alpha = int.Parse(parts[1]);
						lista = new List<T[]>(samples);
						phase = 1;
					}
					else if (phase == 1)
					{
						// Reconoce cada muestra
						if (parts.Length < 2)
						{
							throw new InvalidOperationException("Formato de archivo de secuencias invalido, linea incompleta");
						}
						var sampleLenght = int.Parse(parts[1]);
						if (parts.Length != sampleLenght + 2)
						{
							throw new InvalidOperationException("Formato de archivo de secuencias invalido, dimensiones invalidas");
						}
						// Lee la nueva muestra, convierte cada simbolo
						var sampleInt = parts.Select(x => int.Parse(x));
						var sampleClass = sampleInt.Take(1); // La clase
						var sampleBody = sampleInt.Skip(2); // omite la longitud
						var sample = Enumerable.Concat(sampleClass, sampleBody);
						// convierte al formato target
						var sampleConverted = sample.Select(x => (T)Convert.ChangeType(x, typeof(T))).ToArray();
						lista.Add(sampleConverted);
					}
				}
			}
			return lista.ToArray();
		}

		static int _ToInt(object o)
		{
			return (int)Convert.ChangeType(o, TypeCode.Int32);
		}

		/// <summary>
		/// Almacena un archivo en formato DESTINO, usando como clase el primer elemento de cada secuencia
		/// </summary>
		/// <typeparam name="T">Tipo de dato usado, debe ser un tipo entero</typeparam>
		/// <param name="filename">Archivo a ser guardado</param>
		/// <param name="data">Secuencias</param>
		public static void SavePlain<T>(string filename, IEnumerable<IEnumerable<T>> data) where T : struct
		{
			using (var writer = new StreamWriter(filename))
			{
				var alpha = _ToInt(data.Max(x => x.Skip(1).Max())) + 1;
				writer.WriteLine("{0} {1}", data.Count(), alpha);
				foreach (var sample in data)
				{
					// convierte la clase en entero
					var type = _ToInt(sample.First());
					// convierte la cadena en enteros y luego en cadenas
					var intEnum = sample.Skip(1).Select(x => _ToInt(x).ToString());

					// conforma la cabecera de la linea
					var head = new[] { type.ToString(), intEnum.Count().ToString() };

					// antepone la cabecera
					var line = Enumerable.Concat(head, intEnum);
					var fullLineStr = string.Join(" ", line);
					writer.WriteLine(fullLineStr);
				}
				writer.Close();
			}
		}
	}
}